#pragma once

#include <iostream>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <stdlib.h>
#include <sys/msg.h>
#include <string.h>
#include "Log.hpp"
const int defaultmsgfd = -1;
const int proj_id = 123;
const std::string default_filepath_ = "./tmp";


#define CREATE_MSGQUEU (IPC_CREAT | IPC_EXCL | 0666)
#define GET_MSGQUEUE (IPC_CREAT)
#define MAX_SIZE 1024

#define SERVER 1
#define CLIENT 2
using namespace ns_log;
class MsgQueue
{
private:
    int _msgfd;
    std::string _filepath;
    struct msgbuf 
    {
        long mtype;    
        char mtext[MAX_SIZE];    
    };
public:
    MsgQueue(const std::string &path = default_filepath_) : _msgfd(defaultmsgfd), _filepath(path)
    {
    }

    void Create(int flag)
    {
        key_t key = ftok(_filepath.c_str(), proj_id);
        if (key == -1)
        {
            LOG(FATAL, "创建key失败\n");
            abort();
        }
        _msgfd = msgget(key, flag);
        if (_msgfd == -1)
        {
            LOG(FATAL, "创建消息队列失败\n");
            abort();
        }
        LOG(DEBUG, "创建消息队列done\n");
    }
    bool Recv(int type,std::string* out)
    {
        struct msgbuf buf;
        int n = ::msgrcv(_msgfd,&buf,sizeof(buf.mtext),type,0);
        if(n == -1)
        {
            LOG(ERROR,"读取失败\n");
            return false;
        }
        buf.mtext[n] = 0;
        *out += buf.mtext;
        return true;
    }
    bool Send(int type,const std::string& in)
    {
        struct msgbuf buf;
        memset(&buf, 0, sizeof(buf));
        // 1.拷贝
        buf.mtype = type;
        memcpy(buf.mtext, in.c_str(), in.size());
        // 2.发送
        int n = msgsnd(_msgfd, &buf, sizeof(buf.mtext), 0);
        if (n == -1)
        {
            LOG(ERROR, "发送消息失败\n");
            return false;
        }
        LOG(DEBUG, "发送消息完毕\n");
        return true;
    }
    void Destroy()
    {
        int n = msgctl(_msgfd, IPC_RMID, nullptr);
        if (n == -1)
        {
            LOG(ERROR, "删除消息队列失败\n");
            return;
        }
        LOG(DEBUG, "删除消息队列done\n");
    }
};

class Server : public MsgQueue
{
public:
    Server()
    {
        MsgQueue::Create(CREATE_MSGQUEU);
    }
    // RAII--构造时获取资源，析构时释放资源
    ~Server()
    {
        MsgQueue::Destroy();
    }
};

class Client : public MsgQueue
{
public:
    Client()
    {
        MsgQueue::Create(GET_MSGQUEUE);
    }
    // RAII--构造时获取资源，析构时释放资源
    ~Client()
    {
    }
};
